package ycl.scheduled.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMethod;
import ycl.scheduled.common.models.tencent.maps.Location;
import ycl.scheduled.common.models.tencent.maps.req.ExploreReq;
import ycl.scheduled.common.models.tencent.maps.req.PlaceSearchReq;
import ycl.scheduled.common.models.tencent.maps.req.SuggestionReq;
import ycl.scheduled.common.models.tencent.maps.res.*;
import ycl.scheduled.common.properties.TencentMapProperties;
import ycl.scheduled.common.utils.GpsUtil;
import ycl.scheduled.common.utils.PageUtil;
import ycl.scheduled.service.GpsService;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * 逻辑处理层
 *
 * @author: YCL
 * @date: 2021-09-09 23:05:04
 */
@Slf4j
@Service("gpsService")
public class GpsServiceImpl implements GpsService {

	@Resource
	private TencentMapProperties tencentMapProperties;

	private final String WHOLE_COUNTRY = "全国";


	/**
	 * 获取地图
	 *
	 * @param urlString 请求路径
	 */
	private String getMap(String urlString) {
		StringBuffer result = new StringBuffer();
		try {
			URL url = new URL(urlString);
			HttpURLConnection connection = (HttpURLConnection) url.openConnection();
			connection.setRequestMethod(String.valueOf(RequestMethod.GET));

			BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8));
			String read;
			while ((read = reader.readLine()) != null)
				result.append(read).append("\n");

			reader.close();
		} catch (MalformedURLException e) {
			log.error("url 格式错误, {}", urlString);
			e.printStackTrace();
		} catch (IOException e) {
			log.error("url 请求异常");
			e.printStackTrace();
		}

		System.out.println(result);
		return result.toString();
	}

	@Override
	public BaseGpsQueryRes<PlaceSearchRes> getExplore(ExploreReq req) {
		Integer policy = req.getPolicy();
		if (policy != 1 && policy != 2)
			policy = 1;
		Location location = GpsUtil.getLocation(req);
		StringBuffer url = new StringBuffer()
				.append(getUrl(tencentMapProperties.getPlaceSearchExplore()))
				.append("&boundary=nearby(").append(location.getLat()).append(",").append(location.getLng()).append(",")
				.append(location.getDistance()).append(")")
				.append("&policy=").append(policy);
		return getRes(url, PlaceSearchRes.class);
	}

	@Override
	public BaseGpsQueryRes<PlaceSearchRes> getDetail(String id) {
		StringBuffer url = new StringBuffer()
				.append(getUrl(tencentMapProperties.getPlaceSearchDetail()))
				.append("&id=").append(id);
		return getRes(url, PlaceSearchRes.class);
	}


	/**
	 * 获取路径前缀
	 *
	 * @param searchType 要请求的路径
	 * @return
	 */
	@SuppressWarnings("all")
	private String getUrl(String searchType) {
		StringBuffer buffer = new StringBuffer();
		buffer.append(tencentMapProperties.getPrefixUrl())
				.append(searchType)
				.append("?key=")
				.append(tencentMapProperties.getKey());
		return buffer.toString();
	}

	/**
	 * 请求腾讯返回信息
	 *
	 * @param url 请求路径
	 * @param c   返回的装在泛型里的类
	 * @param <T> 继承gps请求返回值的类
	 * @return 返回请求的返回值
	 */
	@SuppressWarnings("all")
	private <T extends BaseGpsParentRes> BaseGpsQueryRes<T> getRes(StringBuffer url, Class<T> c) {
		System.out.println("传入的类: " + c);
		String res = getMap(url.toString());
		return JSONObject.parseObject(res, BaseGpsQueryRes.class);
	}


	@Override
	public BaseGpsQueryRes<PlaceSearchRes> getPlaceSearch(PlaceSearchReq req) {
		Page<PlaceSearchReq> page = PageUtil.getPage(req, PlaceSearchReq.class);
		Location location = GpsUtil.getLocation(req);
		StringBuffer url = new StringBuffer()
				//https://apis.map.qq.com/ws/place/v1/search?key=UAEBZ-PPM6W-WKSRA-OJZEU-OX4W6-UFFT5
				.append(getUrl(tencentMapProperties.getPlaceSearch()))
				//&boundary=nearby(lat,lng,dis)
				.append("&boundary=nearby(").append(location.getLat()).append(",").append(location.getLng()).append(",")
				.append(location.getDistance()).append(")")

				//&keyword=kw
				.append("&keyword=").append(req.getKeyword())
				//&page_size=ps
				.append("&page_size=").append(page.getSize())
				//&page_index=pi
				.append("&page_index=").append(page.getCurrent());
		return getRes(url, PlaceSearchRes.class);
	}


	@Override
	public BaseGpsQueryRes<SuggestionRes> getSuggestion(SuggestionReq req) {
		StringBuffer url = new StringBuffer()
				.append(getUrl(tencentMapProperties.getKeywordSuggestion()))
				.append("&region=").append(StrUtil.isNotBlank(req.getRegion()) ? req.getRegion() : WHOLE_COUNTRY)
				.append("&keyword=").append(req.getKeyword());
		return getRes(url, SuggestionRes.class);
	}

	@Override
	public BaseGpsQueryRes<AddressResolveRes> addressResolve(String address) {
		System.out.println(WHOLE_COUNTRY);//消除警告用
		StringBuffer url = new StringBuffer()
				.append(getUrl(tencentMapProperties.getAddressResolve()))
				.append("&address=").append(address);
		return getRes(url, AddressResolveRes.class);
	}

	@Override
	public BaseGpsQueryRes<LocationResolveRes> getLocationResolve(Location location) {
		if (! GpsUtil.locationLegalVerify(location))
			throw new IllegalArgumentException("地址不合法");

		StringBuffer url = new StringBuffer()
				.append(getUrl(tencentMapProperties.getAddressResolve()))
				.append("&location=").append(location.getLat()).append(",").append(location.getLng());
		return getRes(url, LocationResolveRes.class);
	}

	@Override
	@SuppressWarnings("all")
	public BaseGpsQueryRes<List<List<DistrictRes>>> districtList() {
		StringBuffer url = new StringBuffer()
				.append(getUrl(tencentMapProperties.getDistrictList()));
		String res = getMap(url.toString());
		return JSONObject.parseObject(res, BaseGpsQueryRes.class);
	}

	@Override
	public List<DistrictRes> districtListProvince() {
		BaseGpsQueryRes<List<List<DistrictRes>>> res = districtList();
		List<List<DistrictRes>> list = res.getResult();
		return list.get(0);
	}

	@Override
	public List<DistrictRes> districtListCity() {
		BaseGpsQueryRes<List<List<DistrictRes>>> res = districtList();
		List<List<DistrictRes>> list = res.getResult();
		return list.get(1);
	}

	@Override
	public List<DistrictRes> districtListArea() {
		BaseGpsQueryRes<List<List<DistrictRes>>> res = districtList();
		List<List<DistrictRes>> list = res.getResult();
		return list.get(2);
	}


	@SuppressWarnings("all")
	private DistrictRes getDistrictRes(Object o) {
		JSONObject j = JSONObject.parseObject(o + "", JSONObject.class);
		String code = j.get("id") + "";
		String name = j.get("name") + "";
		String fullname = j.get("fullname") + "";
		//子节点起终点
		String cidx = j.get("cidx") + "";
		List c = JSONObject.parseObject(cidx, List.class);

		//经纬度
		String location = j.get("location") + "";
		JSONObject l = JSONObject.parseObject(location, JSONObject.class);
		BigDecimal lat = new BigDecimal(l.get("lat") + "");
		BigDecimal lng = new BigDecimal(l.get("lng") + "");
		Location location1 = new Location(lat, lng);

		String pinyin = j.get("pinyin") + "";
		List py = JSONObject.parseObject(pinyin, List.class);
		DistrictRes res = new DistrictRes();
		res.setId(code)
				.setName(name)
				.setFullname(fullname)
				.setCidx(c)
				.setPinyin(py)
				.setLocation(location1);
		return res;
	}


}
